<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>AI对话助手</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#4f46e5',
                        secondary: '#818cf8',
                        light: '#f9fafb',
                        dark: '#1f2937'
                    }
                }
            }
        }
    </script>
    <style>
        .message-container {
            scroll-behavior: smooth;
        }
        .message-container::-webkit-scrollbar {
            width: 6px;
        }
        .message-container::-webkit-scrollbar-track {
            background: #f1f1f1;
        }
        .message-container::-webkit-scrollbar-thumb {
            background: #c7d2fe;
            border-radius: 3px;
        }
        .message-container::-webkit-scrollbar-thumb:hover {
            background: #a5b4fc;
        }
        .typing-indicator {
            display: inline-block;
            width: 8px;
            height: 8px;
            border-radius: 50%;
            background-color: #6b7280;
            margin-right: 4px;
            animation: typing 1.4s infinite ease-in-out both;
        }
        .typing-indicator:nth-child(1) {
            animation-delay: 0s;
        }
        .typing-indicator:nth-child(2) {
            animation-delay: 0.2s;
        }
        .typing-indicator:nth-child(3) {
            animation-delay: 0.4s;
        }
        @keyframes typing {
            0%, 60%, 100% {
                transform: translateY(0);
            }
            30% {
                transform: translateY(-6px);
            }
        }
        .ai-response pre {
            background-color: #f3f4f6;
            padding: 12px;
            border-radius: 6px;
            overflow-x: auto;
        }
        .ai-response code {
            background-color: #f3f4f6;
            padding: 2px 4px;
            border-radius: 4px;
            font-family: monospace;
        }
        .ai-response blockquote {
            border-left: 4px solid #c7d2fe;
            padding-left: 12px;
            margin-left: 0;
            color: #4b5563;
        }
    </style>
</head>
<body class="bg-gray-50 min-h-screen flex flex-col">
<header class="bg-white shadow-sm">
    <div class="max-w-4xl mx-auto px-4 py-4 flex items-center">
        <div class="bg-gradient-to-r from-primary to-secondary w-10 h-10 rounded-lg flex items-center justify-center">
            <i class="fas fa-robot text-white text-xl"></i>
        </div>
        <div class="ml-3">
            <h1 class="text-xl font-bold text-gray-800">AI对话助手</h1>
            <p class="text-sm text-gray-500">基于DeepSeek-R1模型</p>
        </div>
    </div>
</header>

<main class="flex-grow max-w-4xl mx-auto w-full px-4 py-6">
    <div id="messages" class="message-container bg-white rounded-xl shadow-sm p-4 h-[calc(100vh-220px)] overflow-y-auto mb-4">
        <div class="ai-message flex mb-6">
            <div class="flex-shrink-0 w-8 h-8 bg-secondary rounded-full flex items-center justify-center">
                <i class="fas fa-robot text-white text-sm"></i>
            </div>
            <div class="ml-3 max-w-[85%]">
                <div class="bg-gray-100 rounded-2xl rounded-tl-none px-4 py-3 ai-response">
                    <p>您好！我是AI助手，您可以问我任何问题。我会尽力为您提供准确、有用的信息。</p>
                    <p class="mt-2">例如：</p>
                    <ul class="list-disc pl-5 mt-1 space-y-1">
                        <li>解释量子计算的基本概念</li>
                        <li>用JavaScript写一个冒泡排序算法</li>
                        <li>如何学习Python编程？</li>
                    </ul>
                </div>
                <div class="text-xs text-gray-500 mt-1">现在</div>
            </div>
        </div>
    </div>

    <div class="relative">
        <form id="chat-form" class="flex items-center">
            <div class="relative flex-grow">
                <input
                        type="text"
                        id="user-input"
                        placeholder="输入您的问题..."
                        class="w-full py-3 pl-4 pr-12 bg-white border border-gray-300 rounded-full shadow-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-transparent"
                        autocomplete="off"
                >
                <div class="absolute right-3 top-1/2 transform -translate-y-1/2">
                    <button
                            type="submit"
                            id="send-btn"
                            class="w-9 h-9 rounded-full bg-primary hover:bg-primary-dark flex items-center justify-center transition-colors"
                    >
                        <i class="fas fa-paper-plane text-white text-sm"></i>
                    </button>
                </div>
            </div>
        </form>
        <div class="text-xs text-gray-500 text-center mt-2">
            按Enter发送，Shift+Enter换行
        </div>
    </div>
</main>

<script>
    document.addEventListener('DOMContentLoaded', function() {
        const messagesContainer = document.getElementById('messages');
        const chatForm = document.getElementById('chat-form');
        const userInput = document.getElementById('user-input');
        const sendBtn = document.getElementById('send-btn');

        let currentEventSource = null;
        let currentAiMessageId = null;
        let currentAiResponse = '';

        // 处理用户输入
        chatForm.addEventListener('submit', function(e) {
            e.preventDefault();
            const message = userInput.value.trim();

            if (message) {
                // 添加用户消息
                addUserMessage(message);

                // 清空输入框
                userInput.value = '';

                // 禁用发送按钮
                sendBtn.disabled = true;
                sendBtn.classList.add('opacity-50');

                // 添加AI消息占位符
                currentAiMessageId = addAiMessage();

                // 调用API
                callAPI(message);
            }
        });

        // 支持Shift+Enter换行
        userInput.addEventListener('keydown', function(e) {
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                chatForm.dispatchEvent(new Event('submit'));
            }
        });

        // 输入框内容变化时启用/禁用发送按钮
        userInput.addEventListener('input', function() {
            sendBtn.disabled = !userInput.value.trim();
            sendBtn.classList.toggle('opacity-50', !userInput.value.trim());
        });

        // 添加用户消息
        function addUserMessage(message) {
            const timestamp = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});

            const messageElement = document.createElement('div');
            messageElement.className = 'user-message flex justify-end mb-6';
            messageElement.innerHTML = `
                    <div class="max-w-[85%]">
                        <div class="text-xs text-gray-500 text-right mb-1">${timestamp}</div>
                        <div class="bg-primary text-white rounded-2xl rounded-tr-none px-4 py-3">
                            ${escapeHtml(message).replace(/\n/g, '<br>')}
                        </div>
                    </div>
                    <div class="flex-shrink-0 w-8 h-8 bg-primary rounded-full flex items-center justify-center ml-3">
                        <i class="fas fa-user text-white text-sm"></i>
                    </div>
                `;

            messagesContainer.appendChild(messageElement);
            messagesContainer.scrollTop = messagesContainer.scrollHeight;
        }

        // 添加AI消息
        function addAiMessage() {
            const messageId = 'ai-msg-' + Date.now();

            const messageElement = document.createElement('div');
            messageElement.className = 'ai-message flex mb-6';
            messageElement.id = messageId;
            messageElement.innerHTML = `
                    <div class="flex-shrink-0 w-8 h-8 bg-secondary rounded-full flex items-center justify-center">
                        <i class="fas fa-robot text-white text-sm"></i>
                    </div>
                    <div class="ml-3 max-w-[85%]">
                        <div class="text-xs text-gray-500 mb-1">现在</div>
                        <div class="ai-response bg-gray-100 rounded-2xl rounded-tl-none px-4 py-3">
                            <div class="typing-indicator-container">
                                <span class="typing-indicator"></span>
                                <span class="typing-indicator"></span>
                                <span class="typing-indicator"></span>
                            </div>
                        </div>
                    </div>
                `;

            messagesContainer.appendChild(messageElement);
            messagesContainer.scrollTop = messagesContainer.scrollHeight;

            return messageId;
        }

        // 调用API
        function callAPI(message) {
            // 关闭之前的连接（如果有）
            if (currentEventSource) {
                currentEventSource.close();
            }

            // 重置当前响应
            currentAiResponse = '';

            // 构建API URL
            const model = 'deepseek-r1:1.5b';
            const encodedMessage = encodeURIComponent(message);
            const tag = 'personal_info';
            const apiUrl = `http://localhost:8090/api/v1/ollama/generate_stream_rag?model=${model}&message=${encodedMessage}&ragTag=${tag}`;

            // 创建EventSource
            currentEventSource = new EventSource(apiUrl);

            currentEventSource.onmessage = function(event) {
                try {
                    const data = JSON.parse(event.data);

                    // 检查是否有内容
                    if (data.result && data.result.output && data.result.output.content) {
                        currentAiResponse += data.result.output.content;

                        // 更新AI消息
                        updateAiMessage(currentAiResponse);
                    }

                    // 检查是否结束
                    if (data.result && data.result.metadata && data.result.metadata.finishReason === 'STOP') {
                        console.log("流结束，关闭当前事件!")
                        currentEventSource.close();
                        currentEventSource = null;

                        // 启用发送按钮
                        sendBtn.disabled = false;
                        sendBtn.classList.remove('opacity-50');

                        // 更新时间戳
                        updateAiTimestamp();
                    }
                } catch (error) {
                    console.error('解析错误:', error);
                    showError('解析响应时出错');
                }
            };
            currentEventSource.onerror = function() {

                if (null != currentEventSource) {
                    currentEventSource.close();
                    currentEventSource = null;
                }

                // 启用发送按钮
                sendBtn.disabled = false;
                sendBtn.classList.remove('opacity-50');
            };
        }

        // 更新AI消息
        function updateAiMessage(content) {
            if (!currentAiMessageId) return;

            const messageElement = document.getElementById(currentAiMessageId);
            if (!messageElement) return;

            const responseElement = messageElement.querySelector('.ai-response');
            if (responseElement) {
                // 移除输入指示器
                const typingIndicator = responseElement.querySelector('.typing-indicator-container');
                if (typingIndicator) {
                    typingIndicator.remove();
                }

                // 渲染Markdown内容
                responseElement.innerHTML = marked.parse(content);

                // 确保滚动到底部
                messagesContainer.scrollTop = messagesContainer.scrollHeight;
            }
        }

        // 更新AI消息时间戳
        function updateAiTimestamp() {
            if (!currentAiMessageId) return;

            const messageElement = document.getElementById(currentAiMessageId);
            if (!messageElement) return;

            const timestampElement = messageElement.querySelector('.text-gray-500');
            if (timestampElement) {
                timestampElement.textContent = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'});
            }
        }

        // 显示错误信息
        function showError(message) {
            if (!currentAiMessageId) return;

            const messageElement = document.getElementById(currentAiMessageId);
            if (!messageElement) return;

            const responseElement = messageElement.querySelector('.ai-response');
            if (responseElement) {
                // 移除输入指示器
                const typingIndicator = responseElement.querySelector('.typing-indicator-container');
                if (typingIndicator) {
                    typingIndicator.remove();
                }

                responseElement.innerHTML = `<div class="text-red-500"><i class="fas fa-exclamation-circle mr-2"></i>${message}</div>`;
            }

            // 更新时间戳
            updateAiTimestamp();
        }

        // 简单的HTML转义
        function escapeHtml(unsafe) {
            return unsafe
                .replace(/&/g, "&amp;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;")
                .replace(/"/g, "&quot;")
                .replace(/'/g, "&#039;");
        }
    });
</script>
</body>
</html>